Imports System.ComponentModel

Namespace WPF

    ''' <summary>
    ''' An extended WPF ComboBox that works like the ASP.NET AJAX enabled ComboBoxes
    ''' </summary>
    ''' <remarks></remarks>
    Public Class AjaxStyleComboBox
        Inherits ComboBox

#Region " Private Declarations "

        Private _bolKeyBoardActivity As Boolean = False
        Private _intMinimunSearchTextLength As Integer = 1

#End Region

#Region " Properties "

        ''' <summary>
        ''' What is the minimum number of characters the user must enter before they are allowed to request a record search
        ''' </summary>
        <Description("What is the minimum number of characters the user must enter before they are allowed to request a record search"), _
         Category("Custom"), _
         DefaultValue(1)> _
        Public Property MinimunSearchTextLength() As Integer
            Get
                Return _intMinimunSearchTextLength
            End Get
            Set(ByVal Value As Integer)
                _intMinimunSearchTextLength = Value
            End Set
        End Property

#End Region

#Region " RoutedEvents "

        ''' <summary>
        ''' Fires when a record is selected.  This replaces the ComboBox SelectedChanged event
        ''' </summary>
        Public Shared ReadOnly LoadItemsSourceRoutedEvent As RoutedEvent = EventManager.RegisterRoutedEvent("LoadItemsSource", RoutingStrategy.Bubble, GetType(LoadItemsSourceRoutedEventHandler), GetType(AjaxStyleComboBox))

        ''' <summary>
        ''' Fires when the combo box needs its items loaded
        ''' </summary>
        Public Shared ReadOnly RecordSelectedRoutedEvent As RoutedEvent = EventManager.RegisterRoutedEvent("RecordSelected", RoutingStrategy.Bubble, GetType(RecordSelectedRoutedEventHandler), GetType(AjaxStyleComboBox))
        Public Custom Event LoadItemsSource As LoadItemsSourceRoutedEventHandler
            AddHandler(ByVal value As LoadItemsSourceRoutedEventHandler)
                Me.AddHandler(AjaxStyleComboBox.LoadItemsSourceRoutedEvent, value)
            End AddHandler
            RemoveHandler(ByVal value As LoadItemsSourceRoutedEventHandler)
                Me.RemoveHandler(AjaxStyleComboBox.LoadItemsSourceRoutedEvent, value)
            End RemoveHandler
            RaiseEvent(ByVal sender As Object, ByVal e As LoadItemsSourceRoutedEventArgs)
                Me.RaiseEvent(e)
            End RaiseEvent
        End Event

        Public Custom Event RecordSelected As RecordSelectedRoutedEventHandler
            AddHandler(ByVal value As RecordSelectedRoutedEventHandler)
                Me.AddHandler(AjaxStyleComboBox.RecordSelectedRoutedEvent, value)
            End AddHandler
            RemoveHandler(ByVal value As RecordSelectedRoutedEventHandler)
                Me.RemoveHandler(AjaxStyleComboBox.RecordSelectedRoutedEvent, value)
            End RemoveHandler
            RaiseEvent(ByVal sender As Object, ByVal e As RecordSelectedRoutedEventArgs)
                Me.RaiseEvent(e)
            End RaiseEvent
        End Event

#End Region

#Region " Methods "

        Public Sub ClearAll()
            Me.ItemsSource = Nothing
            Me.Text = String.Empty
            Me.IsDropDownOpen = False
        End Sub

        ''' <summary>
        ''' Raises the LoadItemsSource event when the user has entered a search string and pressed ENTER
        ''' </summary>
        Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Input.KeyEventArgs)
            _bolKeyBoardActivity = True

            'this code only runs if the DropDown is not open because if its open the OnPreviewKeyDown code will handle the ENTER key
            If Me.Text.Trim.Length >= Me.MinimunSearchTextLength AndAlso e.Key = Key.Enter Then
                OnLoadItemsSource(New LoadItemsSourceRoutedEventArgs(AjaxStyleComboBox.LoadItemsSourceRoutedEvent, Me, Me.Text))
                Me.IsDropDownOpen = True
                e.Handled = True
                Me.SelectedIndex = -1

            Else
                MyBase.OnKeyDown(e)
            End If

        End Sub

        Protected Overridable Sub OnLoadItemsSource(ByVal e As LoadItemsSourceRoutedEventArgs)
            RaiseEvent LoadItemsSource(Me, e)
            'Karl commented this out so that a record would not be loaded 
            'on the host form until the user actually selected a record.
            'Me.RaiseEvent(New RecordSelectedRoutedEventArgs(AjaxStyleComboBox.RecordSelectedRoutedEvent, Me, Me.SelectedValue))
        End Sub

        ''' <summary>
        ''' Raises the RecordSelected event if the user presses ENTER or TAB
        ''' </summary>
        Protected Overrides Sub OnPreviewKeyDown(ByVal e As System.Windows.Input.KeyEventArgs)
            _bolKeyBoardActivity = True

            If Me.IsDropDownOpen = True AndAlso Me.SelectedIndex > -1 AndAlso (e.Key = Key.Enter OrElse e.Key = Key.Tab) Then
                OnRecordSelected(New RecordSelectedRoutedEventArgs(AjaxStyleComboBox.RecordSelectedRoutedEvent, Me, Me.SelectedValue))
                Me.IsDropDownOpen = False

                e.Handled = True

            ElseIf e.Key = Key.Escape Then
                ClearAll()
                e.Handled = True

            Else
                MyBase.OnPreviewKeyDown(e)
            End If

        End Sub

        Protected Overrides Sub OnPreviewMouseLeftButtonDown(ByVal e As System.Windows.Input.MouseButtonEventArgs)
            _bolKeyBoardActivity = False
            MyBase.OnPreviewMouseLeftButtonDown(e)
        End Sub

        Protected Overridable Sub OnRecordSelected(ByVal e As RecordSelectedRoutedEventArgs)
            RaiseEvent RecordSelected(Me, e)
        End Sub

        ''' <summary>
        ''' Raises the RecordSelected event if the user selects a record with their mouse.
        ''' </summary>
        Protected Overrides Sub OnSelectionChanged(ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
            MyBase.OnSelectionChanged(e)

            If _bolKeyBoardActivity = False Then
                OnRecordSelected(New RecordSelectedRoutedEventArgs(AjaxStyleComboBox.RecordSelectedRoutedEvent, Me, Me.SelectedValue))
            End If

        End Sub

#End Region

    End Class

End Namespace
